home *** CD-ROM | disk | FTP | other *** search
/ Mac100% 1998 November / MAC100-1998-11.ISO.7z / MAC100-1998-11.ISO / オンラインソフト定点観測 / ユーティリティ / Mops 3.2.sea / Mops 3.2 / Mops source / PPC source / cg5 < prev    next >
Text File  |  1998-06-22  |  34KB  |  1,231 lines

  1. marker m__cg5
  2.  
  3. PPC?
  4. [IF]
  5. false    constant    debug?
  6. [ELSE]
  7. false    constant    debug?
  8. [THEN]
  9.  
  10.  
  11. 0    value    distance_code_moved
  12. 0    value    ^fwd
  13. 0    value    last_colon_defn
  14. 0    value    fp_flags?
  15.  
  16.  
  17. forward  PPC_OBJ
  18.  
  19. PPC? not
  20. [IF]
  21. forward  CALL_H            ¥ in PPC mode, these are already forward defined in
  22. forward  LIT_ADDR        ¥  qpClass, which gets loaded before the cgx files.
  23. [THEN]
  24.  
  25. ¥ on the PPC, normal alignment is 4-byte:
  26.  
  27. : ALIGN            align4  ;
  28.  
  29. PPC?
  30. [IF]
  31. : CODE_ALIGN    CDP #align4 -> CDP  ;
  32. [ELSE]
  33. ¥ CODE_ALIGN is in ppcOn68k
  34. [THEN]
  35.  
  36.  
  37. PPC?
  38. [IF]
  39. ¥ we need LITERAL early in this file, since in a number of the following
  40. ¥  words we use  postpone literal  in which we really do want to compile
  41. ¥  a call to this PPC version of literal.
  42.  
  43.  
  44. : LITERAL    ¥ ( n -- )    Compiles a fetch of n as a literal.
  45.     ¥ We just push onto cstk, hoping we can combine with an
  46.     ¥  op at run time.  If dpl is positive, n is a double number.
  47.  
  48.     clear: opnd1
  49.     dpl 0>=
  50.     IF    swap  >lit: opnd1
  51.         opnd1 push
  52.     THEN
  53.     >lit: opnd1
  54.     opnd1 push  ;                immediate
  55.  
  56. [THEN]
  57.  
  58.  
  59.  
  60. ¥        =========  FINALIZATION OF DEFINITIONS  ===========
  61.  
  62. (*    At semicolon time, there are a number of things we have to fix up in
  63.     the definition we just compiled.  Once we've compiled the prolog and
  64.     epilog and added the const_data, if any, the final location of the 
  65.     code is known.  We can then "finalize" the definition.  This includes
  66.     resolving any EXITs and LEAVEs and putting in the correct offsets for
  67.     calls to other words (these couldn't be determined before the code's
  68.     final location was determined).
  69.     
  70.     To handle these various things, we use some pseudo-instructions to stand in
  71.     place of the final instructions we're going to put in those same locations
  72.     at finalization time.  To finalize, we look through the whole definition
  73.     for these pseudo-instructions, and take the appropriate action.
  74.    
  75.     For the pseudo-instructions, we have to use opcodes that can't ever be
  76.     used for real instructions.  So we use the lmw and stmw instructions, since
  77.     these instructions won't always be available in hardware on PPC processors,
  78.     so we never ever want to generate them.
  79.     
  80.     This gives us pseudo-instructions with a top byte in the range B8 - BF.
  81.     
  82.     We also define our handler codes into this same range, since the two-byte
  83.     handler code appears on an aligned boundary.  This will prevent a
  84.     handler code ever being mistaken for an instruction.  Thus all our
  85.     handler codes and pseudo-instructions identify themselves.
  86.    
  87.     So far we've defined these:
  88.    
  89.     BAxx xxxx    call to a Mops word (xx xxxx is code-relative offset)
  90.  
  91.     BBxx xxxx    floating-point flag bytes.  This code is basically for
  92.                    the disassembler, since it's aligned and 3 flag bytes
  93.                    are plenty.  It shouldn't come up in finalization.
  94.  
  95.     BCxx        all handler codes which have no boilerplate code (can't
  96.                 be EXECUTEd).  Unlike on the 68k, xx is unsigned and not
  97.                 doubled (so we can have 256 codes if we need them).
  98.                 
  99.     BDxx        all other handler codes, except for colon defns.  They can
  100.                    be EXECUTEd.
  101.  
  102.     BE00            handler code for a colon defn
  103.     BE01            ditto, but means this is a forward defn.
  104.     BE02            marks the start of :loc code
  105.     BE03            marks the start of :mloc code
  106.     BE04            handler code for a :ppc_proc defn
  107.  
  108.     BE40            method (note BD40 is an inline method - so the 40 always
  109.                        marks a method)
  110.  
  111.             (we'll reserve BExx for any further options on colon definitions.)
  112.    
  113.     These next two can't ever appear inside a definition, so we give an error
  114.     if they're encountered during finalization.
  115.     
  116.     BF01            handler code for SYSCALL and EXTERN
  117.     BF0B            handler code for LIBRARY
  118.     
  119.     BF02 0000    EXIT
  120.     BF03 xxxx    conditional EXIT (xxxx is cond. branch opcode)
  121.     BF04    0000    LEAVE
  122.     BF05 0000    LOOP
  123.     BF06 0000    target of a forward defn.  This marker is redundant,
  124.                     but makes the decompiler output look more sensible.
  125.     
  126.     BF08 xxxx    unconditional branch.  xxxx is offset (we only need 16 bits).
  127.     
  128.     BF09 xxxx    ELSE - branch.  xxxx is initially the offset back to the
  129.                    original conditional branch, in case we delete this branch
  130.                    and need to adjust.  Once the branch is resolved, and we
  131.                    know it won't be deleted, xxxx becomes the branch offset
  132.                    as for other unconditional branches.  We can tell which
  133.                    is which, since the first offset is negative and the
  134.                    second positive.
  135.  
  136.     BF0A        replace with a literal load into r0 of the distance the code
  137.                    is moved.  Used in generating the addr of a location 
  138.                    within the current definition (since we don't know until
  139.                    the end how far it might be moved).
  140.    
  141. *)
  142.  
  143.  
  144.    
  145. 0    value    CURR-DEF-CODE        ¥ when we finish compiling a defn we move
  146.                                 ¥  the code to make room for the prolog -
  147.                                 ¥  this holds the addr of the code proper,
  148.                                 ¥  which we need when we're finalizing.
  149. 0    value    EXIT_LOC
  150. ppc? not
  151. [if]
  152. 0    value    CONST_DATA_START    ¥ PPC version is in pnuc1
  153. [then]
  154. 0    value    1st_defn
  155. 0    value    init_entry
  156.  
  157.  
  158. forward  add_const_data
  159. forward     set_CD_gpr# 
  160. forward  FP_adjust
  161.  
  162. :f set_CD_gpr#  ;f        ¥ the real defn is in zArgs
  163.  
  164.  
  165. : FIX_UNCOND_BRANCH  { pos ¥ thisPos offs -- }
  166.         ¥ due to back-equalization, we can get unconditional branches to
  167.         ¥  other unconditional branches.  We can simplify these here.
  168.         
  169.     pos 2+ w@x  -> offs
  170.     pos -> thisPos
  171.     BEGIN
  172.         offs NIF    ¥ we must have an empty loop!  Force this loop to end...
  173.             false
  174.         ELSE
  175.             offs ++> thisPos
  176.             thisPos w@  $ FFFE and  $ BF08 =
  177.         THEN
  178.     WHILE
  179.         thisPos 2+ w@x  -> offs
  180.     REPEAT
  181.     thisPos pos -  $ 3FFFFFF and  $ 48000000 or        ¥ b instruction
  182.     pos !
  183. ;
  184.  
  185.  
  186. : FIX_EXIT  { pos -- }
  187.     $ 48000000            ¥ b instruction
  188.     exit_loc  pos -  $ 00FFFFFF and
  189.     or  pos !
  190. ;
  191.  
  192. : FIX_CONDITIONAL_EXIT  { pos -- }
  193.     pos @ 16 <<            ¥ cond branch PPC opcode
  194.     exit_loc  pos -  $ 0000FFFF and
  195.     or  pos !
  196. ;
  197.  
  198. : FIX_LEAVE  { pos ¥ target -- }
  199.     pos -> target
  200.     BEGIN                ¥ scan forward to find the next LOOP or +LOOP
  201.         4 ++> target
  202.         target w@ $ BF05 =
  203.     UNTIL
  204.     $ 48000000            ¥ uncond branch opcode
  205.     target  pos -  $ 00FFFFFF and
  206.     or  pos !
  207. ;
  208.  
  209. : FIX_LOOP  { pos -- }        ¥ replaces the LOOP pseudo-op with the first instruction
  210.                             ¥  of the LOOP windup sequence (see comments there)
  211.  
  212.     $ 82B10000  pos !        ¥ lwz       r21/I, (r17/RP)            restore I
  213. ;
  214.  
  215.  
  216. : FIX_CALL  { pos -- }
  217.     pos @  $ 00FFFFFF and            ¥ code area offset to called location
  218.     code_start +  pos -                ¥ make relative to locn of call
  219.     $ 03FFFFFF and  $ 48000001 or    ¥ construct bl instrn
  220.     pos !
  221. ;
  222.  
  223.  
  224. : COMPILE_DISTANCE_MOVED  { pos -- }
  225.     $ 38000000  distance_code_moved or  pos !    ¥ addi r0, 0, dddd
  226. ;
  227.  
  228. : FIX_VARIANT_OP  { pos ¥ vop -- }        ¥ handles BFxx opcodes
  229.     pos 1+ c@  -> vop
  230.     vop
  231.     SELECT[    $ 02    ]=>        pos  fix_exit
  232.           [    $ 03    ]=>        pos  fix_conditional_exit
  233.           [    $ 04    ]=>        pos  fix_leave
  234.           [    $ 05    ]=>        pos  fix_loop
  235.           [    $ 06    ]=>            ¥ ignore this one
  236.           [    $ 08    ],
  237.           [    $ 09    ]=>        pos  fix_uncond_branch
  238.           [    $ 0A    ]=>        pos  compile_distance_moved
  239.  
  240.           DEFAULT=>  cr .h ." illegal variant opcode during finalization"
  241.     ]SELECT
  242.  
  243. ;
  244.  
  245. : FIX_1_OP  { pos op -- }
  246.     op
  247.     SELECT[    $ BA    ]=>        pos  fix_call
  248.           [    $ BF    ]=>        pos  fix_variant_op
  249.           DEFAULT=>  cr .h ." illegal opcode during finalization"
  250.     ]SELECT
  251. ;
  252.  
  253.  
  254. false    value    inhibit_finalization?
  255.  
  256. : FINALIZE_DEFN  { ¥ pos op -- }
  257.     inhibit_finalization?  ?EXIT
  258.     curr-def-code  -> pos
  259.     BEGIN
  260.         pos CDP >=  ?EXIT
  261.         pos c@  -> op
  262.         op  $ F8 and  $ B8 =
  263.         IF    pos op  fix_1_op
  264.         THEN
  265.         4 ++> pos
  266.     AGAIN
  267. ;
  268.  
  269.  
  270. ¥         =========  COMPILATION OF CALLS, EXIT etc.  ===========
  271.  
  272. false    value    LEAF?            ¥ normally set true at colon time, then set false
  273.                                 ¥  when we do a call.  Thus at semicolon time,
  274.                                 ¥  if it's still true, we know this was a leaf
  275.                                 ¥  routine.
  276.  
  277. ¥ false    value    2LEV?            ¥ we may use this similarly, to detect defns
  278.                                 ¥  which aren't leaves, but only call leaves.
  279.                                 ¥ But we're not using it yet.
  280.  
  281. false    value    CTR_CLOBBERED?    ¥ we use this in deciding if we can use
  282.                                 ¥  a branch on the ctr in DO..LOOP and
  283.                                 ¥  FOR..NEXT.
  284.  
  285. 0        value    FP_FLAGS        ¥ we keep these here till semicolon time, when
  286.                                 ¥  we move the definition and put them in the 
  287.                                 ¥  right place.
  288.  
  289.  
  290. : PUSH_LR
  291.     LR>R0 code,
  292.     0 select: GPRs  RP_reg true compPush: GPRs
  293. ;
  294.  
  295. : PULL_LR
  296.     0 select: GPRs
  297.     RP_reg 0 4 compPull: GPRs
  298.     R0>LR code,
  299. ;
  300.  
  301. : LR>TREG            ¥ can be used in a defn if we know what we're doing
  302.     LR>R0  code,  ;        immediate
  303.  
  304. : TREG>LR
  305.     R0>LR  code,  ;        immediate
  306.  
  307.  
  308. : PLentry  { ¥ reg# addr -- }        ¥ handle entry with named parms/locals
  309.  
  310. (* All we do here is set the flag bytes for this definition, and the initial
  311.    cstk.  Everything else is done by compile_prolog, and we don't call that
  312.    until the end, when we know if this is a leaf proc or not.
  313.    We don't set the flag bytes if this is the resolution of a forward
  314.    definition, since the header's been fixed up already (and isn't here anyway).
  315.    (This is handled in qpCond.)
  316.    
  317.    The flag bytes are described in the comments near the start of cg1.
  318. *)
  319.     forward?
  320.     NIF
  321.         curr-def 2 -  -> addr
  322.         #P  15 and  4 <<
  323.         #PL 15 and  or
  324.         addr 1+ c!
  325.         
  326.         #FP     15 and  4 <<
  327.         #FPL 15 and or
  328.         or> fp_flags
  329.     THEN
  330. ¥ now the initial cstk is different to before, if there were parms
  331.     #P  gpr_call_cnt max  #P -  setup_cstk
  332.     #FP fpr_call_cnt max  #FP - setup_fcstk
  333. ;
  334.  
  335.  
  336. : COMPILE_PROLOG&EPILOG  { #gprs_to_save #fprs_to_save ¥ svCDP src dst offs len -- }
  337.  
  338.     leaf?        ¥ leaf procs don't save/restore anything - it's all done in the caller.
  339.                 ¥ So there's no prolog or epilog.  Here we just have to initialize
  340.                 ¥ a couple of values which the caller needs, then get out.
  341.     IF
  342.         curr-def -> curr-def-code
  343.         CDP -> exit_loc
  344.         EXIT
  345.     THEN
  346.  
  347. ¥ Now we work out the prolog size, which will be the distance we need to
  348. ¥ move the code up memory to make room for the prolog.  See the comments
  349. ¥ in cg3 for details on the prolog, which will make sense of these
  350. ¥ machinations.
  351.  
  352.     local?
  353.     IF      8
  354.     ELSE    #gprs_to_save  #P  + 4*
  355.             #fprs_to_save  #FP + 4* +
  356.             8 +
  357.             [ ppc? ] [if]
  358.                 CD_gpr# IF  12 +  THEN
  359.             [then]
  360.     method? IF 8 + THEN        ¥ trying something here
  361.     THEN
  362.  
  363. ¥    method? IF 8 + THEN
  364.  
  365.     tempObj_framesize IF  4+ THEN
  366.     -> offs                        ¥ offs will be the prolog size
  367.  
  368.     forward?
  369.     IF    #P gpr_call_cnt >        ¥ for forward defns, if the no of named parms
  370.         IF    4 ++> offs            ¥  is greater than call_cnt, some parms will
  371.                                 ¥  have to be pulled from mem, so we'll need
  372.                                 ¥  an extra 4 bytes for the SP adjustment.
  373.         THEN
  374.         #FP fpr_call_cnt >
  375.         IF    4 ++> offs
  376.         THEN
  377.     THEN
  378.  
  379.     curr-def -> src
  380.     src offs +  -> dst
  381.     offs
  382.     IF
  383.         CDP src - -> len
  384.         src dst len  move
  385.         src offs erase        ¥ debugging only
  386.         offs ++> CDP
  387.         offs ++> distance_code_moved
  388.     THEN
  389.     CDP -> svCDP  src -> CDP
  390.     
  391.     init_GPRs  init_FPRs            ¥ all regs invalid at the start!
  392.     local?
  393.     IF    0 0 0 0
  394.     ELSE
  395.         #gprs_to_save #P  #fprs_to_save #FP
  396.     THEN
  397.     false  method?  compile_prolog
  398.  
  399.     svCDP -> CDP
  400.     CDP -> exit_loc                    ¥ EXITs resolve to here
  401.     false  method?  compile_epilog
  402.  
  403. ¥ now our default entry point for the whole program is straight after the
  404. ¥  prolog of the last definition compiled (since on initial entry the
  405. ¥  RP isn't set up, so we mustn't execute a prolog!)
  406.  
  407.     init_entry IF  offs ++> init_entry  THEN
  408.     dst -> curr-def-code
  409. ;
  410.  
  411.  
  412. (* Colon uses a new header format incorporating two flag bytes in addition to
  413.    what we use on the 68k, and also has to observe 4-byte alignment for the
  414.    code.  See comments at the start of cg1 for details.
  415. *)
  416.  
  417. : PPC_ENTRY  { fwd? -- 300 }
  418.     ?exec
  419.     fwd? -> forward?            ¥ transfer to our global so we'll
  420.                                 ¥  take special action if we get { ... }
  421.     CDP -> backstop_CDP
  422.     CDP -> fetch_backstop
  423.  
  424.     0 -> basic_block_start        ¥ the idea is that regs passed in will
  425.                                 ¥  have 0 in their opCDP fields, and I 
  426.                                 ¥  don't want to block cascades
  427.                                 ¥  unnecessarily.  Calling the basic block
  428.                                 ¥  start zero is apparently harmless.
  429.     0 -> max_called_#PL
  430.     0 -> max_called_#FPL
  431.     0 -> stk_offset  0 -> distance_code_moved
  432. ¥ [ ppc? ] [if]  0 -> CD_gpr#  [then]
  433.     false -> will_skip?
  434.     false -> ctr_clobbered?
  435.     0 -> fp_flags
  436.     clear: eq_ranges  clear: const_data
  437.  
  438.     gpr_call_cnt setup_cstk            ¥ will be redone if we get { ... }
  439.     fpr_call_cnt setup_fcstk
  440.     fwd?
  441.     IF        false
  442.     ELSE    optimize_leaf_calls?
  443.     THEN  -> leaf?
  444.                 ¥ only set leaf? flag if optimizing leaf calls, and this isn't
  445.                 ¥  a forward definition
  446. ¥    0 >size: control_stk  0 >size: control_flags
  447.     -1 -> gpr_rtn_cnt        ¥ means we haven't set its specific value yet
  448.     -1 -> fpr_rtn_cnt
  449.  
  450. ¥    release: const_data  new: const_data
  451.     0 -> stk_offset
  452. [ PPC? ]
  453. [IF]
  454.     -1 -> state        ¥ same as postpone ] - the only thing we really
  455.                     ¥  need from the 68k (:)
  456. [ELSE]
  457.     (:)
  458. [THEN]
  459.     CDP -> curr-def                ¥ the entry prolog gets added later
  460.     300                            ¥ security marker
  461. ;
  462.  
  463.  
  464. PPC?
  465. [IF]
  466. : :
  467.     CDP -> last_colon_defn        ¥ used by compile_call in checking where
  468.                                 ¥  a call is coming from
  469.     CDP -> const_data_start
  470.     local? NIF  CDP -> CD_gpr_loc  THEN
  471.     1st_defn NIF  CDP -> 1st_defn  THEN
  472.     ppc_header
  473.     $ BE000000 code,        ¥ handler code for PPC colon defns,
  474.                             ¥  and initial flag bytes
  475.     false -> method?
  476.     false -> noname?
  477.     0 >size: control_stk  0 >size: control_flags
  478.     false ppc_entry            ¥ handle ppc proc entry
  479.     postpone hide            ¥ new word is hidden until defn end
  480. ;        ppc_immediate
  481.  
  482.  
  483. : :NONAME  ( -- xt 300 )
  484.     CDP -> const_data_start
  485.     $ BE000000 code,        ¥ no hdr, just handler code for PPC colon defns,
  486.                             ¥  and initial flag bytes
  487.     CDP 2-                    ¥ xt = addr of flag bytes
  488.     false -> method?
  489.     true -> noname?
  490.     false ppc_entry            ¥ handle ppc proc entry
  491. ;
  492.  
  493.  
  494. [ELSE]
  495.  
  496. : :
  497.     PPC?
  498.     IF    CDP -> const_data_start
  499.         1st_defn NIF  CDP -> 1st_defn  THEN
  500.         ppc_header
  501.         $ BE000000 code,        ¥ handler code for PPC colon defns,
  502.                                 ¥  and initial flag bytes
  503.         false -> method?
  504.         false -> noname?
  505.         0 >size: control_stk  0 >size: control_flags
  506.         false ppc_entry            ¥ handle ppc proc entry
  507.         postpone hide            ¥ new word is hidden until defn end
  508.     ELSE
  509.         postpone :
  510.     THEN
  511. ;        immediate
  512.  
  513. [THEN]
  514.  
  515.  
  516. : CompExit
  517. ¥    store_all_pending
  518. ¥    tail_optimize?  ?EXIT
  519.     BLR code,
  520. ;
  521.  
  522. : CLRCOMP
  523.     0 -> #PL  0 -> #FPL
  524.     false -> method?  false -> noname?
  525.     false -> mloc?
  526.     0 -> tempObj_frameSize
  527.     false -> fltFlg
  528. ;
  529.  
  530.  
  531. PPC? [IF]
  532. forward releaseTemps            ¥ in zClass
  533. [THEN]
  534.  
  535. : (;)  { ^flags ¥ loc_addr #gprs_to_save #fprs_to_save -- }
  536.             ¥ factors out common code for ; and ;m
  537.  
  538.     debug? if
  539.         ." (;) here" cr
  540.     then
  541.     
  542.     false -> fp_flags?
  543.  
  544. (*    First, we call set_constData_reg which decides if we're going to
  545.     use one of our locals regs as a base reg for addressing the const
  546.     data area.  Then if we do this, we make this defn non-leaf.  We also
  547.     do this if there are temp objects.  We don't want the extra complexity
  548.     of const data reg or temp object management in the two types of
  549.     calling sequence - one is quite enough!
  550. *)
  551.     
  552. ¥    set_constData_reg        ¥ sets CD_gpr# non-zero if we're using it
  553. ¥    CD_gpr# IF  false -> leaf?  THEN
  554.  
  555.     tempObj_framesize
  556.     IF    false -> leaf?
  557.         [ ppc? ] [if]
  558.             releaseTemps
  559.         [then]
  560.     THEN
  561.     
  562. ¥ now we equalize the stacks according to what we want for a
  563. ¥  return from this definition:
  564.  
  565.     get_rtn_cnts  simple_equalize
  566.  
  567. ¥ now we set up the first flag byte for this defn, unless it was forward.
  568. ¥ The second flag byte was set up at PLentry.  We also set up the FP flag
  569. ¥  bytes if necessary.
  570.  
  571.     forward?
  572.     NIF
  573.         fpr_call_cnt fpr_rtn_cnt <>  #FPL 0<> or  -> fp_flags?
  574.         leaf?  $ 80 and
  575.         ctr_clobbered?    $ 40 and or
  576.         fp_flags?        $ 10 and or
  577.         gpr_rtn_cnt or
  578.         ^flags c!
  579.         
  580.         fp_flags?
  581.         IF  fpr_rtn_cnt  8 <<  or> fp_flags  THEN
  582.     THEN
  583.  
  584.     #PL  max_called_#PL  max  -> #GPRs_to_save
  585.     #FPL max_called_#FPL max  -> #FPRs_to_save
  586.     #GPRs_to_save #FPRs_to_save  compile_prolog&epilog
  587.  
  588.     fp_adjust                ¥ can move the defn
  589.     add_const_data            ¥ ditto
  590.     compExit
  591.     finalize_defn
  592.  
  593. (*    Now if init_entry has been set nonzero, it means this defn has asked to be
  594.     set as the initial entry, by putting the target addr in init_entry.
  595.     We handle the initial entry in a simple way - rather than trying to do
  596.     anything clever with the PEF, we just put a branch at the start of the
  597.     code.  Here if necessary, we resolve that branch to init_entry.  Note we
  598.     don't use resolve_branch, since that's for use within a defn, and assumes a
  599.     16-bit offset, which surely won't be enouyh here.
  600. *)
  601.     init_entry
  602.     IF    init_entry code_start - $ 03FFFFFF and    ¥ offset - should be positive
  603.         code_start @ $ FC000000 and or
  604.         code_start !
  605.         0 -> init_entry
  606.     THEN
  607.     noname? forward? or  NIF  postpone reveal  THEN
  608.     local? NIF  clrComp  0 -> #P  0 -> #FP
  609.                 [ ppc? ] [if]  0 -> CD_gpr#  [then]
  610.            THEN
  611.     0 -> state
  612.     false -> noname?  false -> mloc?
  613. [ ppc? ] [if]
  614.     curr-def-code 32 -  CDP over - 32 +  fix_caches
  615. [then]
  616. ;
  617.  
  618.  
  619. PPC?
  620. [IF]
  621.  
  622. : ;                ppc_immediate
  623.     curr-def 2- (;)
  624.     300 ?defn
  625. ;
  626.  
  627.  
  628. : ;proc
  629.     curr-def 2- (;)
  630.     306 ?defn
  631. ;        ppc_immediate
  632.  
  633.  
  634. : EXIT
  635.         get_rtn_cnts simple_equalize
  636.         $ BF020000  code,            ¥ opcode BF02 = EXIT.  Will be changed
  637.                                     ¥  to an uncond branch to the epilog.
  638.         size: control_flags
  639.         IF  pop: control_flags 4 or  push: control_flags  THEN
  640.                                     ¥ this basic block is now dead!
  641.         CDP -> basic_block_start    ¥ to block hoists - but not much
  642.                                     ¥  point!
  643. ;        ppc_immediate
  644.  
  645.  
  646. : ?EXIT
  647.     " IF EXIT THEN"  evaluate
  648. ;                            ppc_immediate
  649.  
  650. : 0EXIT
  651.     " NIF EXIT THEN"  evaluate
  652. ;                            ppc_immediate
  653.  
  654.  
  655. [ELSE]
  656.  
  657. : ;
  658.     PPC?
  659.     IF
  660.         curr-def 2- (;)
  661. ¥        300 ?defn
  662.         300 <> IF cr ." warning - unbalanced!!" cr THEN
  663.     ELSE
  664.         postpone ;
  665.     THEN
  666. ;                immediate
  667.  
  668. : EXIT
  669.     PPC?
  670.     IF    get_rtn_cnts simple_equalize
  671.         $ BF020000  code,            ¥ opcode BF02 = EXIT.  Will be changed
  672.                                     ¥  to an uncond branch to the epilog.
  673.         size: control_flags
  674.         IF  pop: control_flags 4 or  push: control_flags  THEN
  675.                                     ¥ this basic block is now dead!
  676.         CDP -> basic_block_start    ¥ to block hoists - but not much
  677.                                     ¥  point!
  678.     ELSE
  679.         postpone exit
  680.     THEN
  681. ;        immediate
  682.  
  683.  
  684. : ?EXIT
  685.     PPC?
  686.     IF    " IF EXIT THEN"  evaluate
  687.     ELSE
  688.         postpone ?exit
  689.     THEN  ;                            immediate
  690.  
  691. : 0EXIT
  692.     PPC?
  693.     IF    " NIF EXIT THEN"  evaluate
  694.     ELSE
  695.         postpone 0exit
  696.     THEN  ;                            immediate
  697.  
  698. [THEN]
  699.  
  700.  
  701. 0    value    sv_curr-def
  702. 0    value    sv_#PL
  703. 0    value    sv_#P
  704. 0    value    sv_const_data_start
  705. 0    value    sv_fp_flags
  706. 0    value    sv_CD_gpr#
  707.  
  708.  
  709. (*    (suspend_compilation) and (resume_compilation) are called by [ and ] respectively.
  710.     The problem we have to solve is that when resuming compilation we have to
  711.     restore the code generator state to the same as it was when compilation was
  712.     suspended - i.e. all the reg contents, cstk, etc etc.  To simpilfy this a bit,
  713.     we don't try to save and restore the world, but treat suspension and resumption
  714.     like calling a word with 2 parms and 2 results.  So at suspension time, we
  715.     do a simple_equalize with 2 cells, then at resumption we just initialize
  716.     the regs and cstk back to that state.  This is a bit simpler than what we do
  717.     at call_h, since we're not really calling another word.
  718. *)
  719.  
  720. : (suspend_compilation)
  721.     state  0EXIT
  722.     curr-def  -> sv_curr-def
  723.     #PL -> sv_#PL  #P -> sv_#P
  724.     CD_gpr# -> sv_CD_gpr#
  725.     const_data_start -> sv_const_data_start
  726.     reset: const_data  const_data ->: sv_const_data
  727.     clear: const_data
  728.     fp_flags -> sv_fp_flags
  729.     0 -> fp_flags
  730.     0 -> #PL  0 -> #P
  731.     2 -1 simple_equalize
  732. ;
  733.  
  734. : (resume_compilation)
  735.     sv_curr-def -> curr-def
  736.     sv_#PL -> #PL  sv_#P -> #P
  737.     sv_CD_gpr# -> CD_gpr#
  738.     sv_const_data_start -> const_data_start
  739.     sv_const_data  ->: const_data  clear: sv_const_data
  740.     sv_fp_flags -> fp_flags
  741.     2 setup_cstk  update_refcnts
  742. ;
  743.  
  744.  
  745. ¥    ===================  LITERAL ADDRESSES ===================
  746.  
  747. : (LITADDR)  { gpr# offs -- }
  748.     gpr# >gpr: opnd1
  749.     offs NIF    ¥ this can happen in object binding, so we'll save time
  750.                 ¥  and get rid of it here
  751.         opnd1 push  EXIT
  752.     THEN
  753.     offs >lit: opnd2
  754.     otAdd -> operation
  755.     compRegLit
  756.     res1 push
  757. ;
  758.  
  759.  
  760. (* LITADDR_H handles the generation of an address IN THE DATA AREA.
  761.    (on the 68k we didn't have to distinguish).
  762.    At the xt+2 there will be a reloc pointer to the right place in the
  763.    data area (xt=cfa).
  764.    (For addresses in the code area, use lit_addr)
  765. *)
  766.  
  767. : LITADDR_H  { xt -- }        ¥ We handle this simply as an add of the base reg and
  768.                             ¥  the displacement.
  769.     xt 2+  @b&d  (litaddr)
  770. ;
  771.  
  772.  
  773. ¥ LIT_ADDR just generates an address, regardless of where it is.
  774.  
  775. :f LIT_ADDR  ( addr -- )
  776.     b&d  (litaddr)
  777. ;f
  778.  
  779.  
  780. ¥    ===========  CONSTANT DATA (stored in code area)  =============
  781.  
  782.  
  783. : CODE_ADDR_IN_CURR_DEF  ( addr -- )
  784.     lit_addr
  785.     $ BF0A0000 code,        ¥ at finalization time, is replaced with a load
  786.                             ¥  into r0 of the distance the code is moved
  787.     " treg +" evaluate
  788. ;
  789.  
  790.  
  791. (*    CONST_DATA_REF compiles a push of the addr of the current location
  792.     in the constant data, which we use for literal strings, floating
  793.     point literals, etc etc.
  794.  
  795.     For example, if we have ( addr len ) referring to the data we
  796.     want to add, the normal way to add it would be this:
  797.    
  798.     const_data_ref            ¥ compiles push of addr at run time
  799.     ( addr len ) add: const_data
  800.    
  801.     The constant data for the current definition will be placed straight
  802.     before it in the dictionary.  Thus it will be read-only in installed
  803.     apps.  While we're compiling the defn we put the const data in the
  804.     bytestring const_data, then fix it up at semicolon time, via
  805.     ADD_CONST_DATA.
  806.     
  807.     This mechanism replaces literal strings and w@(IP) stuff that used
  808.     to go in the middle of the code itself.
  809. *)
  810.  
  811. : CONST_DATA_REF  { ¥ gpr# displ -- }
  812.     0 -> svOpcode
  813.     const_data_start  pos: const_data +        ¥ the addr we want
  814.     b&d  -> displ -> gpr#
  815. [ ppc? ] [if]
  816.     displ true 16bits? nip
  817.     NIF
  818.         CD_gpr# NIF  set_CD_gpr#  THEN        ¥ sets CD_gpr#
  819.         CD_gpr#
  820.         IF                                    ¥ if successful, we use it
  821.             false -> leaf?
  822.             CD_gpr# -> gpr#
  823.             const_data_start CD_gpr_loc -  pos: const_data +
  824.             -> displ
  825.         THEN
  826.     THEN
  827. [then]
  828.     gpr# displ  (litaddr)
  829. ;
  830.  
  831.  
  832. ppc? not
  833. [IF]
  834. 0    value    prev_link        ¥ saves prev link to current method - in
  835. [THEN]                        ¥  ppc mode, it's in cg-class which gets
  836.                             ¥  loaded first
  837.  
  838.  
  839. ¥ FP_ADJUST and ADD_CONST_DATA may put some info at or before the start of
  840. ¥  the definition, and move it up in memory to make room.  These can't be
  841. ¥  called until semicolon time, since all their info mightn't be there
  842. ¥  till then.
  843.  
  844. :f FP_ADJUST { ¥ dist -- }
  845.     fp_flags?  0EXIT
  846.  
  847.     curr-def                    ¥ src
  848.     dup 4+                      ¥ dst
  849.     CDP curr-def -                ¥ len for move
  850.     move
  851.  
  852. ¥ now we adjust some other things, since we just moved the definition:
  853.  
  854.     4 ++> distance_code_moved
  855.     4 ++> curr-def    4 ++> curr-def-code
  856.     4 ++> CDP  4 ++> exit_loc
  857.  
  858.     init_entry IF  4 ++> init_entry  THEN
  859.     
  860. ¥ now we move the FP flag bytes into the area we made for it
  861.  
  862.     fp_flags  $ BB000000 or  curr-def 4- !
  863. ;f
  864.  
  865.     
  866. :f ADD_CONST_DATA  { ¥ dist -- }
  867.     reset: const_data
  868.     len: const_data  0EXIT
  869.  
  870. ¥ first we move the whole defn down to make room for the const data.
  871. ¥  At this point const_data_start will point to the link field of
  872. ¥  the current definition, or our marker word if it's a forward
  873. ¥  or :noname definition.
  874.  
  875.     len: const_data  #align4  -> dist
  876.  
  877.     forward? noname? or  mloc? or
  878.     NIF
  879.         method?
  880.         IF
  881.         [ ppc? ] [if]
  882.             dist negate ^meth_link +!            ¥ update method's link field
  883.         [else]
  884.             dist negate const_data_start 4+ +!    ¥ update method's link field
  885.         [then]
  886.             dist  prev_link  +!
  887.         ELSE
  888.             dist
  889.             const_data_start 4+            ¥ start of name field - note, can't use
  890.                                         ¥  "curr-def >name" as it's a PPC header!
  891.             thread  +!                            ¥ incr CONTEXT entry by dist
  892.             dist negate const_data_start +!        ¥ and update dic link for this defn
  893.             dist ++> latest
  894.         THEN
  895.     THEN
  896.  
  897.     const_data_start                    ¥ src
  898.     dup dist +                          ¥ dst
  899.     CDP const_data_start -                ¥ len for move
  900.     move
  901.  
  902. ¥ now we adjust some other things, since we just moved the definition:
  903.  
  904.     dist ++> distance_code_moved
  905.     dist ++> curr-def    dist ++> curr-def-code
  906.     dist ++> CDP  dist ++> exit_loc
  907.  
  908.     init_entry IF  dist ++> init_entry  THEN
  909.     
  910. ¥ now we copy the const data into the area we made for it
  911.  
  912.     all: const_data
  913.     const_data_start  swap  move
  914. ;f
  915.  
  916.  
  917. PPC? [IF]
  918.  
  919. : RELOC>CONST_DATA        ¥ ( xt -- )   Just needed to support XTS{ in zBase,
  920.                         ¥  since at that point we can't send messages yet so we
  921.                         ¥  can't manipulate const_data directly.
  922.     0 +L: const_data
  923.     ^1st: const_data 4-
  924.     reloc!
  925. ;
  926.  
  927. [THEN]
  928.  
  929.  
  930. (*    CALL_EXTERN handles an external call.  This requires that we set things up as
  931.     the PowerPC volume of IM says:
  932.  
  933. 1.    We have a pointer which is resolved by the CFM - this will
  934.     be the address of a transition vector.  This pointer will be in the
  935.     data area (since it gets changed), and has a reloc addr pointing
  936.     to it in the code area, which belongs to the SYSCALL or EXTERN
  937.     word.
  938.     
  939.     We have to allow for new external calls to be asked for, then
  940.     executed straight away, so we use a scheme where when we do an
  941.     external call, we check whether the pointer has been resolved
  942.     yet, and resolve it if it hasn't.  We can easily tell, since we
  943.     initialize each pointer to nilP, which is an illegal address.
  944.     This test and the call to FindSymbol to resolve it, is in
  945.     get_transition_vector which is called at the beginning of our
  946.     external call sequence.
  947.     
  948.     We could save a couple of instructions by pre-resolving symbols that
  949.     are already in the dictionary image, but it's not worth it - it's 
  950.     better to use just one scheme, and we do need to be able to resolve
  951.     on demand, so that's the way we do it.
  952.  
  953.     The transition vector has 2 addresses - the addr for us to branch to,
  954.     and the new RTOC value.  The dest addr has to be loaded into the CTR
  955.     or the LR for us to use it as a branch target.  We use the CTR - see
  956.     below for the reason for this.  We want to load the dest addr as early
  957.     as possible so that instruction fetching won't stall, so we do this
  958.     part of the setup before we equalize the stack - during the equalization
  959.     nothing needs the CTR anyway.
  960.     
  961.     We use r12 for the addr of the transition vector itself, as IM says.
  962.     This also won't get messed with during equalization.
  963.     
  964.     We set up r12 and the CTR in get_transition_vector, as well as resolving
  965.     the symbol as described above.  Factoring as much as possible into
  966.     get_transition_vector saves code space in the call sequence for
  967.     external calls.
  968.     
  969.     So, as well as a bit of housekeeping, the main thing that CALL_EXTERN
  970.     does is to compile a call to get_transition_vector.  CALL_EXTERN then
  971.     passes 1 as an "xt" to CALL_H.  1 can never be a real xt, since they must
  972.     be even, so this tells call_h that this is an external call.  CALL_H
  973.     looks after everything from here on, including the stack equalization.
  974.  
  975.  
  976. 2.  The first thing call_h does is pass 1 to EQUALIZE_FOR_CALL (in the
  977.     equalization section).  This gets the parameters into the right regs (and
  978.     the parameter area, if necessary), as needed for external calls.
  979.  
  980.     IM envisages that setting the SP is already done by the prolog
  981.     of the current routine, on behalf of all external calls that this
  982.     routine makes.  The parameter area is big enough for the call with the
  983.     most parameters, and the others leave some unused space below the parm
  984.     area (actually higher in memory).  The parm area for each call must come
  985.     immediately below the linkage area, so the callee can find it.
  986.     
  987.     But in Mops we have a separate data stack pointer, so we simply
  988.     set up a linkage area for external calls using the system SP (gpr1) at
  989.     startup time, and never change it after that.
  990.  
  991. 3.    call_h then calls COMPILE_EXTERN_CALL to compile the actual call.  To do
  992.     this, we store our own RTOC into the linkage area (actually this is done
  993.     once and for all at startup since we have a permanent frame for external
  994.     calls),    and load RTOC from the transition vector (still pointed to by r12).
  995.     We then bctrl (branch and link to count register) to call the external 
  996.     code.  (We could equally well have used the LR - see below.)
  997.  
  998.  
  999. Note: the standard sequence for cross-TOC calls in Metrowerks C is as
  1000. follows.  We do much the same, but in a different order - in particular
  1001. we grab the dest addr and get it into the CTR as early as possible, before
  1002. we normalize the stack etc., and we move the SP to allocate the parm and
  1003. linkage areas on each call.
  1004.  
  1005. We could equally well have used the LR instead of the CTR.  MW have to use
  1006. the CTR since they've done a bl to the out-of-line code, and have to preserve
  1007. the LR.  But the IBM manual recommends using the CTR for computed branches
  1008. like this, to make life easier for debuggers etc, so that's what we'll do.
  1009.  
  1010. inline:
  1011.         bl        xxx
  1012.         lwz        r2/TOC, $14(r1/SP)
  1013.         ...
  1014.     
  1015.  
  1016. xxx        lwz        r12, <offs>(r2/TOC)    / TOC entry is a pointer to transfer vector
  1017.         stw        r2/TOC, $14(r1/SP)    / Save RTOC
  1018.         lwz        r0, (r12)            / 1st entry in TV is destination addr
  1019.         lwz        r2/TOC, $4(r12)        / 2nd entry is new TOC addr - put in RTOC
  1020.         mtspr    CTR, r0                / dest addr to CTR
  1021.         bctr                        / branch there
  1022.  
  1023. *)
  1024.  
  1025. : CALL_EXTERN  { ^extern -- }
  1026.     ?comp
  1027.     false -> leaf?  true -> ctr_clobbered?
  1028.     ^extern lit_addr                ¥ generate the addr of the extern for
  1029.                                     ¥  get_transition_vector
  1030.     " get_transition_vector" evaluate    ¥ (which isn't defined till setup)
  1031.                                     ¥ at run time, it resolves if nec, gets
  1032.                                     ¥ TV addr to r12 and dest addr to ctr
  1033.  
  1034.     ^extern c@        -> #extern_parm_cells
  1035.     ^extern 1+ c@    -> #extern_result_cells
  1036.     ^extern 2+ c@    -> #extern_FP_parms
  1037.     ^extern 3 + c@    -> #extern_FP_results
  1038.     ^extern 4+  w@    -> extern_mask
  1039.  
  1040.     1 call_h                        ¥ 1 means we're doing an extern call, and
  1041.                                     ¥  causes compile_extern_call to be called
  1042. ;
  1043.  
  1044.  
  1045. (* (TOC_CALL) is for internal use only - it compiles a call to one
  1046.    of our predefined TOC symbols.  We  need these in order to be able
  1047.    to set everything up at initial entry time.
  1048. *)
  1049.  
  1050. :f (TOC_CALL)  { #parm-cells #result-cells offs -- }
  1051.     #result-cells    -> #extern_result_cells
  1052.     #parm-cells     -> #extern_parm_cells
  1053.     0                -> #extern_FP_parms
  1054.     0                -> #extern_FP_results
  1055.     $ 81820000 offs or  code,
  1056.                         ¥ lwz  r12, <offs>(r2)    - get trans vect addr to r12
  1057.     $ 800C0000  code,    ¥ lwz  r0, (r12)         - get dest addr to r0
  1058.     $ 7C0903A6  code,    ¥ mtctr r0                 - and then to ctr
  1059.     1 call_h
  1060.     false -> leaf?  true -> ctr_clobbered?
  1061. ;f
  1062.  
  1063.  
  1064. : COMPILE_EXTERN_CALL
  1065.  
  1066. (*    compiles the instructions to do an external call.  r12 points to the
  1067.     transition vector in the called container.  Note that we have our frame
  1068.     for external calls permanently set up, and never change gpr1.  Thus we save
  1069.     our RTOC when we set up the frame in SETUP, and don't need to do it here 
  1070.     on each call.
  1071. *)
  1072.  
  1073.     $ 90410014    code,        ¥ stw  RTOC,20(sys_SP)    - save RTOC in frame
  1074.     $ 804C0004 code,        ¥ lwz  RTOC, 4(r12)        - new TOC addr to RTOC
  1075.     $ 4E800421 code,        ¥ bctrl                    - call external code
  1076.     $ 80410014 code,        ¥ lwz  RTOC, $14(SP)    - on return, restore RTOC
  1077. ;
  1078.  
  1079.  
  1080. PPC?
  1081. [IF]
  1082.  
  1083. : COMPILE_CALL  { ^code ¥ seg# displ -- }
  1084.  
  1085. (*    Compiles a normal Mops call.  Mostly this will be a straight
  1086.     bl to the target, since the effective 24 bits displacement can
  1087.     get us anywhere we need to go, within the current segment.
  1088.     For this we here use pseudo-opcode BA with the offset relative
  1089.     to code_start in the lo 3 bytes, and resolve at finalization time.
  1090.     (The use of code_start is just a convenience since it's easier than
  1091.     working out what's the right segment at finalization time, and
  1092.     we're always compiling in the main dic anyway).
  1093.     The reason for doing things this way, is that the definition can get
  1094.     moved at the beginning of finalization, when we compile the prolog.
  1095.     So the offset for the branch can't be worked out until after that.
  1096.  
  1097.     But if the call is out of the segment, we have to get the addr
  1098.     into the CTR and compile a bctrl.  In this case it won't be affected
  1099.     if the defn moves, so we handle the whole thing here.
  1100. *)
  1101.  
  1102.     CDP addr>S&D drop        ¥ leave CDP's seg#
  1103.     ^code addr>S&D  -> displ  -> seg#
  1104.     seg# =
  1105.     IF            ¥ local branch - we use $BA code - note we make it relative
  1106.                 ¥  to code_start so offset will always fit in 24 bits.  We're
  1107.                 ¥  always compiling in the main dic so this will always be OK.
  1108.         $ BA000000
  1109.         ^code code_start -  or  code,        ¥ offset MUST be positive - 
  1110.                                             ¥  if for some reason it's not, that's
  1111.                                             ¥  a bug, and we'll trap on an illegal
  1112.                                             ¥  instruction!
  1113.         
  1114.     ELSE        ¥ The call is into a different segment.  We'll normally dispatch
  1115.                 ¥ via the segment table, and set up r15-16 for the called segment.
  1116.                 ¥ There are a couple of special cases that will save a few
  1117.                 ¥ instructions.
  1118.         seg# 8 =
  1119.         IF                ¥ We're calling the main dic, so we know we can use r13.
  1120.             mainCode_reg  
  1121.             displ  code_start + nuc_code_start -  half_displ_range -
  1122.                             ¥ displ is rel to code_start, but reg points into
  1123.                             ¥  the middle of the 64k range starting at 
  1124.                             ¥  nuc_code_start
  1125.             (litAddr)        ¥ compile code to generate addr, push reg reference
  1126.         ELSE
  1127.             seg# segTable_entry 4+ lit_addr
  1128.             postpone @
  1129.             displ postpone literal  postpone +
  1130.         THEN
  1131.         opnd1 pop
  1132.         gpr: opnd1  21 <<
  1133.         $ 7C0903A6 or  code,            ¥ mtctr rN
  1134.         $ 4E800421 code,                ¥ bctrl
  1135.         true -> ctr_clobbered?            ¥ we used the ctr
  1136.         free: opnd1
  1137.     THEN
  1138. ;
  1139.  
  1140.  
  1141. [ELSE]
  1142.  
  1143. : COMPILE_CALL  { ^code -- }
  1144.     $ BA000000
  1145.     ^code code_start -  or  code,
  1146. ;
  1147.  
  1148. ¥ In the PPC compilation, these next 2 are in pnuc4.
  1149.  
  1150. : XT?  { xt ¥ code -- xt b }    ¥  Checks if xt is really a legal xt.
  1151.     xt                                    ¥ we'll return this
  1152.     xt 2- 3 and  IF false EXIT  THEN    ¥ 2 less must be aligned
  1153.     xt 2- c@ -> code                    ¥ top byte of handler
  1154.     code $ BD =  code $ BE = or
  1155. ;
  1156.  
  1157. : ?XT    ¥ ( xt -- xt )
  1158.     xt? NIF     ." not a valid xt" 1 die  THEN
  1159. ;
  1160.  
  1161. [THEN]
  1162.  
  1163.  
  1164. :f CALL_H  { xt ¥ svLocal? cFloat? cFwd? ^code -- }
  1165.  
  1166.     local? -> svLocal?  false -> local?  false -> leaf?
  1167.     false -> cFloat?  false -> cFwd?
  1168.  
  1169.     xt 1 =                    ¥ 1 is valid as an "xt" here
  1170.     NIF    xt ?xt drop            ¥ otherwise must be a legal xt
  1171.         xt 2+  -> ^code        ¥ normal case
  1172.         xt 2- w@  $ BE01 =  -> cFwd?    ¥ $ BE01 handler code means forward
  1173.     THEN
  1174.  
  1175.     xt equalize_for_call    ¥ also does method handling if this is a method
  1176.                             ¥  (see e.g. setup_normal_call in cg3)
  1177.     xt 1 and
  1178.     NIF
  1179.     ¥ normal Mops call - we use temp opcode BA and resolve at the end of the defn
  1180.     ¥ First we have to check if it's an FP defn:
  1181.     
  1182.         xt c@ $ 10 and            ¥ floating?
  1183.         IF  true -> cFloat?  4 ++> ^code  THEN
  1184.  
  1185.         ^code compile_call
  1186.         
  1187.     ¥ now we set things up as they need to be on return from the word we called
  1188.  
  1189.         cLeaf? IF  true  cMeth?  compile_epilog  THEN
  1190.         
  1191.         cFwd?
  1192.         IF    true -> ctr_clobbered?        ¥ we have to be conservative
  1193.         THEN
  1194.  
  1195.         xt c@
  1196.         dup $ 40 and  IF  true -> ctr_clobbered?  THEN
  1197.         $ F and                    ¥ # GPRs with results
  1198.  
  1199.         cFloat?
  1200.         IF                        ¥ called word has FP flag bytes
  1201.             xt 4+ c@ $ F and    ¥ in which case #FPRs with results is given
  1202.         ELSE
  1203.             fpr_call_cnt        ¥ otherwise we use the default - same as entry
  1204.         THEN
  1205.  
  1206.         ( #fprs )  reset_fcstk
  1207.         ( #gprs )  reset_cstk
  1208.  
  1209.         debug? if
  1210.             ." normal call compiled.  cstks after:" cr
  1211.             printall: cstk  printall: fcstk
  1212.             ."     fpr_rtn_cnt "  fpr_rtn_cnt . cr
  1213.         then
  1214.  
  1215.         update_refcnts
  1216.         false -> cLeaf?  false -> cMeth?    ¥ finished with them now
  1217.  
  1218.     ELSE            ¥ external call
  1219.         compile_extern_call
  1220.         
  1221.         #extern_result_cells reset_cstk
  1222.         #extern_FP_results     reset_fcstk
  1223.         
  1224.     THEN
  1225.     CDP -> backstop_CDP  CDP -> basic_block_start
  1226.     svLocal? -> local?
  1227. ;f
  1228.  
  1229. : CALLSTR_H        call_h  ;
  1230.  
  1231.